﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using EchoFramework;
using Unity.VisualScripting;
using UnityEngine;

/// <summary>
/// 关卡管理器
/// </summary>
public class LevelManager : MonoBehaviour
{
    private static LevelManager instance;

    public static LevelManager Instance => instance;

    /// <summary>
    /// Grid父节点
    /// </summary>
    [SerializeField]
    private Transform gridParent;

    /// <summary>
    /// 玩家
    /// </summary>
    [SerializeField]
    private GameObject playerObj;

    /// <summary>
    /// 格子
    /// </summary>
    [SerializeField]
    private GameObject gridItem;

    [SerializeField]
    private Transform bg;

    /// <summary>
    /// 关卡格子二维数组
    /// </summary>
    private GridData[,] gridArr;

    /// <summary>
    /// 关卡预测格子二维数组  用于行动预测
    /// </summary>
    private GridData[,] predictGridArr;

    /// <summary>
    /// 关卡行
    /// </summary>
    private int rowCnt;

    /// <summary>
    /// 关卡列
    /// </summary>
    private int columnCnt;

    /// <summary>
    /// 玩家起始/终止点
    /// </summary>
    private Vector2 startOrEndPos;

    /// <summary>
    /// 入口点
    /// </summary>
    private Vector2 entryPoint = CommonParam.Vector2None;

    /// <summary>
    /// 局部终点
    /// </summary>
    private Vector2 localEndPoint = CommonParam.Vector2None;

    /// <summary>
    /// 出口点
    /// </summary>
    private Vector2 exitPoint = CommonParam.Vector2None;

    /// <summary>
    /// 是否需要停止检测
    /// </summary>
    private bool needStopCheck;

    /// <summary>
    /// 关卡中颜色墙GridData字典
    /// key:颜色
    /// value: Grid列表
    /// </summary>
    private Dictionary<EColor, List<GridData>> colorGridDataDict = new Dictionary<EColor, List<GridData>>();

    /// <summary>
    /// 关卡中预测数据颜色墙GridData字典
    /// key:颜色
    /// value: GridData列表
    /// </summary>
    private Dictionary<EColor, List<GridData>> predictColorGridDataDict = new Dictionary<EColor, List<GridData>>();

    /// <summary>
    /// 关卡中颜色GridItem字典
    /// key:颜色
    /// value: GridItem列表
    /// </summary>
    private Dictionary<EColor, List<GridItem>> colorGridItemDict = new Dictionary<EColor, List<GridItem>>();

    /// <summary>
    /// 条件数量
    /// </summary>
    public int LevelTargetCnt { get; private set; }

    /// <summary>
    /// 当前关卡
    /// </summary>
    public int CurLevel
    {
        get;
        private set;
    }

    /// <summary>
    /// 摄像机配置字典
    /// key:关卡
    /// value:对应配置
    /// </summary>
    private Dictionary<int, CameraConfig> cameraCfgDict;

    /// <summary>
    /// 起始点/终点
    /// </summary>
    [HideInInspector]
    public GridItem startOrEndGridItem = null;

    /// <summary>
    /// 当前递归次数
    /// </summary>
    private int curRecursiveCnt;

    /// <summary>
    /// 缓存正式的预测数组
    /// </summary>
    private GridData[,] cacheGridArr;

    /// <summary>
    /// 最大关卡数
    /// </summary>
    public int MaxLevelCnt
    {
        get;
        private set;
    }

    private void Awake()
    {
        if (instance != null)
        {
            Destroy(instance.gameObject);
        }

        instance = this;
        InitInfo();
        EventCenter.Instance.Register(EventType.CloseLevelManager, CloseLevelManager);
    }

    /// <summary>
    /// 初始化信息
    /// </summary>
    private void InitInfo()
    {
        if (cameraCfgDict == null)
        {
            cameraCfgDict = new Dictionary<int, CameraConfig>();
            TextAsset cameraCfgAsset = Resources.Load<TextAsset>("CameraConfig/CameraConfig");
            string[] rowArr = cameraCfgAsset.text.Split('\n');
            int tempRowCnt = rowArr.Length - 1;
            int tempColumnCnt = rowArr[0].Split('\t').Length;
            for (int i = 1; i < tempRowCnt; i++)
            {
                string[] columnArr = rowArr[i].Split('\t');
                for (int j = 0; j < tempColumnCnt; j++)
                {
                    int cfgLevel = Convert.ToInt32(columnArr[0]);
                    float cfgX = Convert.ToSingle(columnArr[1]);
                    float cfgY = Convert.ToSingle(columnArr[2]);
                    float cfgSize = Convert.ToSingle(columnArr[3]);
                    float cfgBgX = Convert.ToSingle(columnArr[4]);
                    float cfgBgY = Convert.ToSingle(columnArr[5]);
                    float cfgBgScaleX = Convert.ToSingle(columnArr[6]);
                    float cfgBgScaleY = Convert.ToSingle(columnArr[7]);
                    cameraCfgDict[cfgLevel] = new CameraConfig(cfgX, cfgY, cfgSize, cfgBgX, cfgBgY, cfgBgScaleX, cfgBgScaleY);
                }
            }

            MaxLevelCnt = cameraCfgDict.Count;
            Debug.Log("最大关卡：" + MaxLevelCnt);
        }
    }
    

    /// <summary>
    /// 加载关卡
    /// </summary>
    /// <param name="level">关卡</param>
    public void LoadLevel(int level)
    {
        CurLevel = level;
        ClearLevel();
        CameraAdjust();
        ReadInfo();
        CreatePlayer();
        GenerateLevel();
        EventCenter.Instance.Execute(EventType.UpdateLevelTxt);
    }

    /// <summary>
    /// 清空关卡
    /// </summary>
    private void ClearLevel()
    {
        for (int i = gridParent.childCount - 1; i >= 0; i--)
        {
            Destroy(gridParent.GetChild(i).gameObject);
        }

        if (PlayerController.Instance != null)
        {
            Destroy(PlayerController.Instance.gameObject);
        }
    }

    /// <summary>
    /// 摄像机调整
    /// </summary>
    private void CameraAdjust()
    {
        if (GMUIView.OpenGM)
            return;

        if(cameraCfgDict == null)
            InitInfo();
        
        if (!cameraCfgDict.ContainsKey(CurLevel))
        {
            Debug.LogError("缺少当前关卡的摄像机配置！");
            return;
        }

        CameraConfig curCameraCfg = cameraCfgDict[CurLevel];
        Camera.main.transform.position = new Vector3(curCameraCfg.X, curCameraCfg.Y, Camera.main.transform.position.z);
        Camera.main.orthographicSize = curCameraCfg.Size;
        bg.localPosition = new Vector3(curCameraCfg.BgX, curCameraCfg.BgY, bg.localPosition.z);
        bg.localScale = new Vector3(curCameraCfg.BgScaleX, curCameraCfg.BgScaleY, bg.localScale.z);
    }

    /// <summary>
    /// 读取信息
    /// </summary>
    private void ReadInfo()
    {
        string[] rowArr = null;
        if (GMUIView.OpenGM)
        {
            string path = Application.streamingAssetsPath + $"/Level{CurLevel}.txt";
            // Debug.LogError(path);
            rowArr = File.ReadAllLines(path);
        }
        else
        {
            TextAsset textAsset = Resources.Load<TextAsset>($"LevelConfig/Level{CurLevel}");
            if (textAsset == null)
            {
                Debug.LogError("读取关卡信息为null！");
                return;
            }

            rowArr = textAsset.text.Split('\n');
        }

        LevelTargetCnt = 0;
        rowCnt = GMUIView.OpenGM ? rowArr.Length : rowArr.Length - 1;
        columnCnt = rowArr[0].Split('\t').Length;
        Debug.Log("行数：" + rowCnt + "   列数：" + columnCnt);

        colorGridDataDict.Clear();
        predictColorGridDataDict.Clear();
        gridArr = new GridData[columnCnt, rowCnt];
        predictGridArr = new GridData[columnCnt, rowCnt];
        for (int i = 0; i < rowCnt; i++)
        {
            string[] columnArr = rowArr[i].Split('\t');
            for (int j = 0; j < columnCnt; j++)
            {
                string[] args = columnArr[j].Split(':');
                int x = j;
                int y = rowCnt - i - 1;
                EGridType gridType = (EGridType) Convert.ToInt32(args[0]);
                EColor gridColor = EColor.None;
                EDirection gridDirection = EDirection.None;
                ESwitchBtnType gridSwitchBtnType = ESwitchBtnType.None;
                switch (gridType)
                {
                    case EGridType.None:
                    case EGridType.Road:
                    case EGridType.StartOrEnd:
                    case EGridType.Target:
                    case EGridType.Wall:
                        if (args.Length > 1) //多个参数代表该墙是特殊墙
                        {
                            gridColor = CommonParam.ColorDict[args[1]];
                            gridDirection = CommonParam.DirectionDict[args[2]];
                        }

                        gridArr[x, y] = new GridData(x, y, gridType, gridColor, gridDirection);
                        break;
                    case EGridType.SwitchBtn:
                        if (args.Length <= 1)
                        {
                            Debug.LogError("参数错误！");
                            return;
                        }

                        gridSwitchBtnType = (ESwitchBtnType) Convert.ToInt32(args[1]);
                        gridColor = CommonParam.ColorDict[args[2]];
                        gridArr[x, y] = new GridData(x, y, gridType, gridSwitchBtnType, gridColor);
                        break;
                }

                //条件数量记录
                if (gridArr[x, y].GridType == EGridType.Target)
                    LevelTargetCnt++;

                //玩家初始点
                if (gridArr[x, y].GridType == EGridType.StartOrEnd)
                    startOrEndPos = new Vector2(x, y);

                predictGridArr[x, y] = gridArr[x, y].GetCloneGirdData();
                if (gridType == EGridType.Wall && CommonParam.SwitchColorList.Contains(gridColor))
                {
                    if (!colorGridDataDict.ContainsKey(gridColor))
                        colorGridDataDict[gridColor] = new List<GridData>();
                    colorGridDataDict[gridColor].Add(gridArr[x, y]);

                    if (!predictColorGridDataDict.ContainsKey(gridColor))
                        predictColorGridDataDict[gridColor] = new List<GridData>();
                    predictColorGridDataDict[gridColor].Add(predictGridArr[x, y]);
                }
            }
        }
    }

    /// <summary>
    /// 生成关卡
    /// </summary>
    private void GenerateLevel()
    {
        colorGridItemDict.Clear();
        if (gridArr == null)
        {
            Debug.LogError("关卡数组有误！");
            return;
        }

        for (int y = 0; y < rowCnt; y++)
        {
            for (int x = 0; x < columnCnt; x++)
            {
                GridData gridData = gridArr[x, y];
                if (gridData == null)
                {
                    Debug.LogError("格子数据为Null！");
                    continue;
                }

                BuildGameCube(gridData);
            }
        }
    }

    /// <summary>
    /// 生成游戏Grid
    /// </summary>
    private void BuildGameCube(GridData gridData)
    {
        GameObject obj = Instantiate(gridItem, gridParent);
        obj.transform.position =
            new Vector2(gridData.X * CommonParam.UnitVar, gridData.Y * CommonParam.UnitVar);
        GridItem item = obj.GetOrAddComponent<GridItem>();
        item.SetData(gridData);
        if (gridData.GridType == EGridType.Wall && CommonParam.SwitchColorList.Contains(gridData.GridColor))
        {
            if (!colorGridItemDict.ContainsKey(gridData.GridColor))
                colorGridItemDict[gridData.GridColor] = new List<GridItem>();
            colorGridItemDict[gridData.GridColor].Add(item);
        }
        else if (gridData.GridType == EGridType.StartOrEnd)
        {
            startOrEndGridItem = item;
        }
    }

    /// <summary>
    /// 克隆真实数组到预测数组
    /// </summary>
    private void Clone2PredictGridArr()
    {
        for (int i = 0; i < columnCnt; i++)
        {
            for (int j = 0; j < rowCnt; j++)
            {
                predictGridArr[i, j] = gridArr[i, j].GetCloneGirdData();
            }
        }
    }

    /// <summary>
    /// 计算路径
    /// </summary>
    /// <param name="pos">坐标点</param>
    /// <param name="direction">方向</param>
    /// <returns>实际可以移动的点</returns>
    public Vector2 GetDestination(Vector2 pos, EDirection direction)
    {
        curRecursiveCnt = 0;
        needStopCheck = false;
        entryPoint = pos; //入口点默认为本身  用于处理不可以移动的情况
        localEndPoint = CommonParam.Vector2None;
        exitPoint = CommonParam.Vector2None;
        Clone2PredictGridArr();
        CalculateDestination(pos, direction);

        if (exitPoint == CommonParam.Vector2None) //出口点无效
        {
            return entryPoint;
        }

        return localEndPoint;
    }

    /// <summary>
    /// 计算路径
    /// </summary>
    /// <param name="pos">坐标点</param>
    /// <param name="direction">方向</param>
    /// <returns>实际可以移动的点</returns>
    private Vector2 CalculateDestination(Vector2 pos, EDirection direction)
    {
        if (curRecursiveCnt > CommonParam.MaxRecursiveCnt) //达到最大递归次数  防止死循环
            return pos;
        curRecursiveCnt++;
        if (needStopCheck)
        {
            return pos;
        }

        Vector2 tempPos = pos;
        switch (direction)
        {
            case EDirection.Up:
                tempPos += Vector2.up;
                break;
            case EDirection.Down:
                tempPos += Vector2.down;
                break;
            case EDirection.Left:
                tempPos += Vector2.left;
                break;
            case EDirection.Right:
                tempPos += Vector2.right;
                break;
        }

        EDirection refDirection = direction;
        if (!CheckGrid(pos, tempPos, ref refDirection))
        {
            return pos;
        }

        return CalculateDestination(tempPos, refDirection);
    }

    /// <summary>
    /// 检查格子是否可站立
    /// </summary>
    /// <param name="previousPos">前一坐标点</param>
    /// <param name="pos">需要检测的坐标点</param>
    /// <param name="direction">方向</param>
    /// <returns>返回是否可行</returns>
    private bool CheckGrid(Vector2 previousPos, Vector2 pos, ref EDirection direction)
    {
        int x = (int) pos.x;
        int y = (int) pos.y;
        if (x < 0 || x > columnCnt)
            return false;
        if (y < 0 || y > rowCnt)
            return false;
        GridData gridData = predictGridArr[x, y];
        bool ret = true;
        switch (gridData.GridType)
        {
            case EGridType.None:
                ret = false;
                break;
            case EGridType.Road:
                ret = true;
                if (localEndPoint == CommonParam.Vector2None)
                    entryPoint = pos;
                else
                    exitPoint = pos;
                break;
            case EGridType.StartOrEnd:

                if (localEndPoint == CommonParam.Vector2None)
                {
                    entryPoint = pos;
                    //若已达到通关条件，需要处理为已通关,使得不要路过终点
                    if (PlayerController.Instance.IsFinishCondition)
                    {
                        needStopCheck = true;
                    }
                }
                else
                {
                    exitPoint = pos;
                }

                break;
            case EGridType.Target: //目标物不会阻碍移动
                ret = true;
                if (localEndPoint == CommonParam.Vector2None)
                    entryPoint = pos;
                else
                    exitPoint = pos;
                break;
            case EGridType.Wall:
                ret = CheckWallGrid(previousPos, pos, ref direction);
                break;
            case EGridType.SwitchBtn: //开关会改变关卡数组，需要刷新格子数据
                CheckSwitchBtn(pos);
                ret = true;
                if (localEndPoint == CommonParam.Vector2None)
                    entryPoint = pos;
                else
                    exitPoint = pos;
                // if (!isCache && PlayerController.Instance.IsPlayerTrigger)
                // {
                //     isCache = true;
                //     CacheGridArr();
                // }
                break;
        }

        return ret;
    }

    /// <summary>
    /// 检查墙格子是否可通行
    /// </summary>
    /// <param name="previousPos">前一坐标点</param>
    /// <param name="pos">当前坐标点</param>
    private bool CheckWallGrid(Vector2 previousPos, Vector2 pos, ref EDirection direction)
    {
        bool ret = true;
        GridData gridData = predictGridArr[(int) pos.x, (int) pos.y];
        bool preGridIsLeft = previousPos.x < gridData.X;
        bool preGridIsRight = previousPos.x > gridData.X;
        bool preGridIsUp = previousPos.y > gridData.Y;
        bool preGridIsDown = previousPos.y < gridData.Y;

        //第一个方向格子为局部终点  前一个坐标为入口点
        if (gridData.GridDirection != EDirection.None && localEndPoint == CommonParam.Vector2None)
        {
            localEndPoint = pos;
        }

        switch (gridData.GridDirection)
        {
            case EDirection.None:
                ret = false;
                break;
            case EDirection.Left:
                ret = preGridIsRight;
                break;
            case EDirection.Right:
                ret = preGridIsLeft;
                break;
            case EDirection.Up:
                ret = preGridIsDown;
                break;
            case EDirection.Down:
                ret = preGridIsUp;
                break;
            case EDirection.LeftRight:
                ret = preGridIsLeft || preGridIsRight;
                break;
            case EDirection.UpDown:
                ret = preGridIsUp || preGridIsDown;
                break;
            case EDirection.LeftUp:
                ret = preGridIsLeft || preGridIsUp;
                if (preGridIsLeft)
                    direction = EDirection.Up;
                if (preGridIsUp)
                    direction = EDirection.Left;
                break;
            case EDirection.UpRight:
                ret = preGridIsUp || preGridIsRight;
                if (preGridIsUp)
                    direction = EDirection.Right;
                if (preGridIsRight)
                    direction = EDirection.Up;
                break;
            case EDirection.RightDown:
                ret = preGridIsRight || preGridIsDown;
                if (preGridIsRight)
                    direction = EDirection.Down;
                if (preGridIsDown)
                    direction = EDirection.Right;
                break;
            case EDirection.DownLeft:
                ret = preGridIsLeft || preGridIsDown;
                if (preGridIsLeft)
                    direction = EDirection.Down;
                if (preGridIsDown)
                    direction = EDirection.Left;
                break;
        }

        return ret;
    }

    /// <summary>
    /// 开关检测 
    /// </summary>
    /// <param name="pos"></param>
    private void CheckSwitchBtn(Vector2 pos)
    {
        int x = (int) pos.x;
        int y = (int) pos.y;
        GridData gridData = predictGridArr[x, y];
        if (!CommonParam.SwitchColorList.Contains(gridData.GridColor))
            return;
        if (gridData.IsBtnCanUse)
        {
            ColorGridListChange(gridData.GridColor, true);
            if (gridData.GridSwtichBtnType == ESwitchBtnType.Single)
            {
                gridData.SetBtnUse(false);
            }
        }
    }

    /// <summary>
    /// 颜色GridList数据发生变化，表现无变化
    /// </summary>
    /// <param name="color">颜色</param>
    /// <param name="isPredict">是否是预测数据</param>
    public void ColorGridListChange(EColor color, bool isPredict = false)
    {
        List<GridData> gridDataList = isPredict ? predictColorGridDataDict[color] : colorGridDataDict[color];
        if (gridDataList == null)
        {
            Debug.LogError("数据为 Null!");
            return;
        }

        foreach (var item in gridDataList)
        {
            int x = item.X;
            int y = item.Y;
            if (isPredict)
            {
                predictGridArr[x, y].TriggerSwitchLogic();
            }
            else
            {
                gridArr[x, y].TriggerSwitchLogic();       
            }
            
            // item.TriggerSwitchLogic();
        }
    }

    /// <summary>
    /// 返回颜色墙ColorItemList
    /// </summary>
    /// <param name="color">颜色</param>
    public List<GridItem> GetColorGridItemList(EColor color)
    {
        if (!colorGridItemDict.ContainsKey(color))
        {
            Debug.Log("GridItemDict不存在该颜色：" + color);
            return null;
        }

        return colorGridItemDict[color];
    }

    /// <summary>
    /// 创建玩家
    /// </summary>
    private void CreatePlayer()
    {
        GameObject obj = Instantiate(playerObj, transform);
        PlayerController pc = obj.GetComponent<PlayerController>();
        obj.transform.position =
            new Vector2(startOrEndPos.x * CommonParam.UnitVar, startOrEndPos.y * CommonParam.UnitVar);
        pc.SetPos(startOrEndPos);
    }

    /// <summary>
    /// 获取格子数据
    /// </summary>
    public GridData GetGridData(int x, int y)
    {
        if (x < columnCnt && y < rowCnt)
            return gridArr[x, y];
        return null;
    }

    /// <summary>
    /// 关闭关卡管理器
    /// </summary>
    private void CloseLevelManager(EventObject eventObject)
    {
        Destroy(gameObject);
    }

    private void OnDestroy()
    {
        EventCenter.Instance.UnRegiseterByAction(EventType.CloseLevelManager, CloseLevelManager);
    }
}